package tech.yixiyun.framework.kuafu.plugins.hotdeploy;

import tech.yixiyun.framework.kuafu.bean.BeanContext;
import tech.yixiyun.framework.kuafu.bean.BeanDefinition;
import tech.yixiyun.framework.kuafu.bean.BeanMode;
import tech.yixiyun.framework.kuafu.boot.bootedhandler.IBootedHandler;
import tech.yixiyun.framework.kuafu.component.Component;
import tech.yixiyun.framework.kuafu.component.ComponentRegistry;
import tech.yixiyun.framework.kuafu.config.AppConfig;
import tech.yixiyun.framework.kuafu.controller.annotation.Controller;
import tech.yixiyun.framework.kuafu.controller.interceptor.IControllerInterceptor;
import tech.yixiyun.framework.kuafu.controller.interceptor.InterceptorContext;
import tech.yixiyun.framework.kuafu.controller.request.param.IRequestParamResolver;
import tech.yixiyun.framework.kuafu.controller.request.param.ParamValueResolverContext;
import tech.yixiyun.framework.kuafu.controller.route.RouteContext;
import tech.yixiyun.framework.kuafu.db.datasource.IDataSourceProvider;
import tech.yixiyun.framework.kuafu.db.sql.handler.BaseRowProcessor;
import tech.yixiyun.framework.kuafu.domain.DomainContext;
import tech.yixiyun.framework.kuafu.domain.DomainDefinition;
import tech.yixiyun.framework.kuafu.enhance.EnhanceKit;
import tech.yixiyun.framework.kuafu.enhance.hancer.IEnhancer;
import tech.yixiyun.framework.kuafu.log.LOGGER;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * 监听到文件改动后的处理器
 *
 * @author Yixiyun
 * @version 1.0
 * @date 2021-05-15 12:30
 */
public class HotDeployHandler {



    public static void handle(ChangeLog log) {
        if (log.isClass()) {
            handleClass(log);
        } else {
            handleFile(log);
        }
    }

    /**
     * 处理配置文件变动
     * @param log
     */
    private static void handleFile(ChangeLog log) {
        LOGGER.warn("监测到{}发生变动，如果该文件是配置文件，可能需要重启应用以使其生效", log.getPath());
        if (log.getPath().contains("-config.json") || log.getPath().contains("-config-test.json")) { //配置文件改动
            AppConfig.reloadAllConfig();
            return;
        }
    }


    private static final List<Consumer<ChangeLog>> extraMonitors = new ArrayList<>();

    /**
     * 注册额外的监听器
     * @param consumer
     */
    public static synchronized void registerExtraMonitor(Consumer<ChangeLog> consumer) {
        extraMonitors.add(consumer);
    }

    /**
     * 处理类文件变动
     * @param log
     */
    private static void handleClass(ChangeLog log) {


        if (log.getChangeType() == Change.ADD) {
            LOGGER.trace("监测到{}类创建", log.getPath());
            ComponentRegistry.register(log.getPath());
            extraMonitors.forEach(m -> m.accept(log));
            return;
        }




        if (log.getChangeType() == Change.UPDATE) {
            handleClassUpdate(log.getPath());
            extraMonitors.forEach(m -> m.accept(log));
            return;
        }

        if (log.getChangeType() == Change.DELETE) {
            handleClassDelete(log.getPath());
            extraMonitors.forEach(m -> m.accept(log));
            return;
        }




    }

    private static void handleClassDelete(String className) {
        LOGGER.trace("监测到{}类删除", className);
        DomainDefinition domainDefinition = DomainContext.getDomainDefinition(className);
        if (domainDefinition != null) {
            DomainContext.unregister(domainDefinition.getDomainClass());
            return;
        }

        BeanDefinition beanDefinition = BeanContext.getBeanDefinition(className);

        if (beanDefinition != null) {
            Class clazz = beanDefinition.getOriginalClass();
            BeanContext.unRegister(clazz);



            //如果是一个Controller
            Controller controller = (Controller) clazz.getAnnotation(Controller.class);
            if (controller != null) {
                RouteContext.unregister(clazz);
                return;
            }


            if (IEnhancer.class.isAssignableFrom(clazz)) {
                LOGGER.warn("检测到Enhancer类删除，需要重启程序才可生效");
                return;

            }

            //如果是个拦截器
            if (IControllerInterceptor.class.isAssignableFrom(clazz)) {
                InterceptorContext.unregister(clazz);
                return;
            }

            //数据源
            if (IDataSourceProvider.class.isAssignableFrom(clazz)) {
                LOGGER.warn("检测到数据源删除，需要重启程序才可生效");
                return;
            }


            //请求解析的
            if (IRequestParamResolver.class.isAssignableFrom(clazz)) {
                ParamValueResolverContext.unregister(clazz);
                return;
            }


            BaseRowProcessor.unregister(clazz);

        }



    }

    private static void handleClassUpdate(String className) {
        LOGGER.trace("监测到{}类发生改变", className);

        DomainDefinition domainDefinition = DomainContext.getDomainDefinition(className);
        if (domainDefinition != null) {
            DomainContext.unregister(domainDefinition.getDomainClass());
            DomainContext.register(domainDefinition.getDomainClass());
            return;
        }


        BeanDefinition beanDefinition = BeanContext.getBeanDefinition(className);
        //是一个Bean类
        if (beanDefinition != null) {
            //更新依赖关系
            Class clazz = beanDefinition.getOriginalClass();
            BeanContext.updateDependClasses(clazz);

            if (beanDefinition.getBeanMode() == BeanMode.SINGLETON) {
                BeanContext.inject(beanDefinition.getInstance(), clazz);
            }

            //更新动态代理
            Class[] enhanceClasses = EnhanceKit.getEnhanceClasses(clazz);
            beanDefinition.setEnhancerClasses(enhanceClasses);


            //如果是一个Controller
            Controller controller = (Controller) clazz.getAnnotation(Controller.class);
            if (controller != null) {
                RouteContext.unregister(clazz);
                RouteContext.register(clazz);
                return;
            }




            if (IBootedHandler.class.isAssignableFrom(clazz)) {
                LOGGER.warn("监测到BootedHandler发生变动，需要重启程序才可生效");
                return;
            }
            if (IDataSourceProvider.class.isAssignableFrom(clazz)) {
                LOGGER.warn("监测到数据源发生变动，需要重启程序才可生效");
                return;
            }



            BaseRowProcessor.unregister(clazz);

        }


    }











    /**
     * 判断是不是组件类
     * @param clazz
     * @return
     */
    private static boolean isComponent(Class clazz) {
        Annotation[] annotations = clazz.getAnnotations();
        if (annotations != null) {
            for (Annotation annotation : annotations) {
                if (annotation.annotationType().isAnnotationPresent(Component.class)) {
                    return true;
                }
            }
        }

        while (clazz != null && clazz != Object.class) {
            Class[] interfaces = clazz.getInterfaces();
            if (interfaces != null && interfaces.length > 0) {
                for (Class in : interfaces) {
                    if (in.isAnnotationPresent(Component.class)) {
                        return true;
                    }
                }
            }
            clazz = clazz.getSuperclass();
        }

        return false;



    }
}
